using System;
using NUnit.Framework;
using Pine.Core;
using Pine.Compiler.Utils;

namespace UnitTests
{
	[TestFixture()]
	public class TestScopes
	{
		private static void AssertSingleResult(ValueList rl, Value value, string sizeMessage, string resultErrorMessage) {
			Assert.AreEqual(1, rl.Size, sizeMessage);
			Assert.AreEqual(rl.GetArrayElement(0), value, resultErrorMessage);
		}
		
		[Test]
		public void TestSimpleScope()
		{
			ValueList rl = new ValueList();
			
			Compiler.ExecuteString("test-simple-scope-1", "main", @"\main() {
				var i = 1;
				return i;
			}", rl, null);
			
			AssertSingleResult(rl, new Number(1), "Expected single result", "Incorrect value");
			
			Compiler.ExecuteString("test-simple-scope-2", "main", @"\main() {
				var i = 1;
				{
					i = 2;
				}
				return i;
			}", rl, null);
			
			AssertSingleResult(rl, new Number(2), "Expected single result", "Incorrect value");
			
			Compiler.ExecuteString("test-simple-scope-3", "main", @"\main() {
				var i = 1;
				{
					var i = 2;
				}
				return i;
			}", rl, null);
			
			AssertSingleResult(rl, new Number(1), "Expected single result", "Incorrectly using variable from nested scope");
		}
		
		[Test]
		public void TestVariableDeclarationScopes() {
			ValueList rl = new ValueList();
			
			Compiler.ExecuteString("test-vardecl-scope", "main", @"\main() {
				var i = 1;
				{
					if (true) return i;
					var i = 2;
				}
				return i;
			}", rl, null);
			
		
			AssertSingleResult(rl, new Number(1), "Using variable value before it was declared", "Using variable value before it was declared");
			
			Compiler.ExecuteString("test-vardecl-scope", "main", @"\main() {
				var i = 1;
				{
					var f = function() { return i; };
					var i = 2;
					return f();
				}
			}", rl, null);
			
			AssertSingleResult(rl, new Number(1), "Capturing variable value before it was declared", "Capturing variable value before it was declared");
		}
	}
}

